package com.ruoyi.system.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.system.domain.dto.*;
import com.ruoyi.system.service.OneMapFwService;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * @author QiuYuchun
 * Date: 2023/12/17
 * Time: 16:24
 */

@Service
@Slf4j
public class OneMapFwServiceImpl implements OneMapFwService {

    @Autowired
    private RestTemplate restTemplate;

    private final String BBEB_ASSISTANT_API = "http://10.1.79.76:6666/GPT/";
    private final String DIVSEARCHMOCK = "http://10.1.79.76:6666/divSearchMock";
    private final String GETDETAILMOCK = "http://10.1.79.76:6666/getDetailMock";
    private final String RIVER_LIST = "https://gatewayproxy-jcpt.mwr.cn/riverlist/river?k=i9WtoogbY2DVdk6mILy5yQ==";
    private final String RIVER_DETAIL = "https://gatewayproxy-jcpt.mwr.cn/riverdetails/getElementDetailNoEncrypt?k=qKa4F5YwHuxjT2EQl6BJoA==";

    //把输入的问题拆解成 步骤-工具
    @Override
    public String getDismantledQuery(String query) {

        String dismantleQueryPrompt = "你现在是一个河流专家，你现在有两个工具来辅助解决用户问题，分别是“按行政区划查询河流名录工具”和“河流详情查询工具”，通常为了解决用户问题，你可以根据用户问题中的意图使用“按行政区划查询河流名录工具”来获得和用户问题答案相关的河流列表（包含河流名称和河流代码），也可以使用“河流详情查询工具”来根据合适的河流的代码获取河流详细信息以满足用户需求，当然，你可以决定如何调用工具的数量和顺序，比如如果用户直接提供了河流代码，你只需要调用“河流详情查询工具”以查询详细信息。\n" +
                "你现在不需要回答用户问题或者调用这两个工具，而是需要把用户的问题按照工具进行拆分，按顺序列出来，你需要生成一个JSON来表示工具的调用，对于每个工具，需要你描述需要用这个工具来干什么。比如当用户的问题是“列出流经北京市的河流”，你的回答JSON就应当为：\n" +
                "{[{\"工具调用\":\"按行政区划查询河流名录工具\"，\"调用期望\":\"我需要找出流经北京的所有河流\"}]}";
        List<MessagesDto> messages = new ArrayList<>();
        MessagesDto sysPrompt = new MessagesDto("system",dismantleQueryPrompt);
        MessagesDto shot1User = new MessagesDto("user","用户问题：我想要知道所有流经南京市鼓楼区的所有河流的长度\\n你的回答：");
        MessagesDto shot1Ass = new MessagesDto("assistant","[\n" +
                "    {\n" +
                "    \"工具调用\": \"按行政区划查询河流名录工具\",\n" +
                "    \"调用期望\": \"查找所有经过南京市鼓楼区的河流\"\n" +
                "    },\n" +
                "    {\n" +
                "    \"工具调用\": \"河流详情查询工具\",\n" +
                "    \"调用期望\": \"查询所有“按行政区划查询河流名录工具”结果列表中河流的详细信息\"\n" +
                "    }\n" +
                "  ]");
        MessagesDto shot2User = new MessagesDto("user","用户问题：查询代码为C0001H的河流的详细信息\\n你的回答：");
        MessagesDto shot2Ass = new MessagesDto("assistant","[\n" +
                "    {\n" +
                "    \"工具调用\": \"河流详情查询工具\",\n" +
                "    \"调用期望\": \"查找河流代码为C0001H的河流的详细信息\",\n" +
                "    }\n" +
                "  ]");
        MessagesDto shotQuery = new MessagesDto("user","用户问题："+ query +"n你的回答：");
        messages.add(sysPrompt);
        messages.add(shot1User);
        messages.add(shot1Ass);
        messages.add(shot2User);
        messages.add(shot2Ass);
        messages.add(shotQuery);

        LLMDto llmDto = new LLMDto();
        llmDto.setMessages(messages);

        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);

        String requestJson = JSON.toJSONString(llmDto);
        log.info("requestJson:{}",requestJson);
        HttpEntity<String> requestEntity = new HttpEntity<>(requestJson, httpHeaders);
        ResponseEntity<JSONObject> responseEntity = restTemplate.exchange(URI.create(BBEB_ASSISTANT_API), HttpMethod.POST,requestEntity,JSONObject.class);
        log.info(String.valueOf(responseEntity.getBody()));

        JSONObject ans = responseEntity.getBody();
        // 获取 choices 数组
        JSONArray choicesArray = ans.getJSONArray("choices");

        // 获取 content 元素的字符串表示
        String contentString = choicesArray.getJSONObject(0)
                .getJSONObject("message")
                .getString("content");

        // 将 content 字符串解析为 List<StepDto>
        List<StepDto> stepDtoList = new ArrayList<>();
        List<Map<String, String>> resultList = JSON.parseObject(contentString, List.class);

        for (Map<String, String> map : resultList) {
            String stepQuery = map.get("调用期望");
            String stepToolName = map.get("工具调用");

            StepDto stepDto = new StepDto(stepQuery, stepToolName);
            stepDtoList.add(stepDto);
        }

        // 检查结果
        String tmp = "无";
        String finalAns = "";
        for (StepDto stepDto : stepDtoList) {
//            System.out.println("工具调用: " + stepDto.getStepQueryl());
//            System.out.println("调用期望: " + stepDto.getStepToolName());
            String stepQuery = stepDto.getStepQueryl();
            if(stepDto.getStepToolName().equals("按行政区划查询河流名录工具") ){
                String stepAns = divSearch(stepQuery);
                tmp = "“按行政区划查询河流名录工具”结果列表中河流的详细信息为：" + stepAns;
                finalAns = stepAns;
            }else{
                String stepAns = detailSearch(stepQuery,tmp);
                finalAns = stepAns;
            }
        }
        String answer = "LLM的回答为：" + finalAns;
        return answer;
    }

    @Override
    public String getRiverList(RiverListDto riverListDto) {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
//        // 使用 setter 方法来填入数据
//        riverListDto.setPageIndex(1);
//        riverListDto.setPageSize(10);
//        riverListDto.setRelationFlag("2");
//
//        // 创建并添加 Relation 对象
//        RiverListDto.Relation relation = new RiverListDto.Relation();
//        relation.setLevel("1");
//        relation.setCode(Arrays.asList("C"));
//        riverListDto.setRelationList(Arrays.asList(relation));
//
//        // 创建并添加 Param 对象
//        RiverListDto.Param param = new RiverListDto.Param();
//        param.setCode("rv_name");
//        param.setName("河流名称");
//        param.setCompareType(3);
//        param.setValue("永定河");
//        riverListDto.setParams(Arrays.asList(param));

        // 使用 JSON.toJSONString(riverListDto) 来将这个对象转换为 JSON 字符串
        String riverListJson = JSON.toJSONString(riverListDto);
        HttpEntity<String> requestEntity = new HttpEntity<>(riverListJson, httpHeaders);
        log.info("=========================请求fw名录接口===============================");
        ResponseEntity<String> responseEntity = restTemplate.exchange(URI.create(RIVER_LIST),HttpMethod.POST,requestEntity,String.class);
        log.info(String.valueOf(responseEntity.getBody()));
        log.info("========================请求返回结果 ↑↑↑===============================");
        String ans = responseEntity.getBody();




        return ans;
    }

    @Override
    public String getRiverDetail(RiverDetailDto riverDetailDto) {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        String riverDetailJson = JSON.toJSONString(riverDetailDto);
        HttpEntity<String> requestEntity = new HttpEntity<>(riverDetailJson, httpHeaders);
        log.info("=========================请求fw名录接口===============================");
        ResponseEntity<String> responseEntity = restTemplate.exchange(URI.create(RIVER_DETAIL),HttpMethod.POST,requestEntity,String.class);
        log.info(String.valueOf(responseEntity.getBody()));
        log.info("========================请求返回结果 ↑↑↑===============================");
        String ans = responseEntity.getBody();
        return ans;
    }


    public String divSearch(String query){
        String divSearchPrompt = "你是一位河流专家，你擅长使用“按河流名称查询河流名录工具”来对河流进行检索，以辅助解决客户的问题。\n" +
                "“按河流名称查询河流名录工具”的输入格式为JSON格式，具体格式如下\n" +
                "{\"工具名称\":\"按河流名称查询河流名录工具\",\"河流名称\":\"\"}\n" +
                "\"河流名称\"中的参数需要你填入用户问题中意图查询的河流名称。\n" +
                "你现在需要借助“按河流名称查询河流名录工具”来辅助解决用户的问题\n" +
                "你的回答只能包含JSON";
        List<MessagesDto> messages = new ArrayList<>();
        MessagesDto sysPrompt = new MessagesDto("system",divSearchPrompt);
        MessagesDto shot1User = new MessagesDto("user","用户问题：查找所有的秦淮河\\n你的回答：");
        MessagesDto shot1Ass = new MessagesDto("assistant","{\"工具名称\":\"按河流名称查询河流名录工具\",\"河流名称\":\n");
        MessagesDto shotQuery = new MessagesDto("user","用户问题："+ query +"n你的回答：");
        messages.add(sysPrompt);
        messages.add(shot1User);
        messages.add(shot1Ass);
        messages.add(shotQuery);

        LLMDto llmDto = new LLMDto();
        llmDto.setMessages(messages);

        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);

        String requestJson = JSON.toJSONString(llmDto);
        log.info("requestJson:{}",requestJson);
        HttpEntity<String> requestEntity = new HttpEntity<>(requestJson, httpHeaders);
        ResponseEntity<JSONObject> responseEntity = restTemplate.exchange(URI.create(BBEB_ASSISTANT_API), HttpMethod.POST,requestEntity,JSONObject.class);
        log.info(String.valueOf(responseEntity.getBody()));

        JSONObject ans = responseEntity.getBody();
        // 获取 choices 数组
        JSONArray choicesArray = ans.getJSONArray("choices");

        // 获取 content 元素的字符串表示
        String contentString = choicesArray.getJSONObject(0)
                .getJSONObject("message")
                .getString("content");
        log.info("去查第三方工具_名录");
        String name = "{\"name\":\"AAA\"}";
        HttpEntity<String> requestEntity2 = new HttpEntity<>(name, httpHeaders);
        ResponseEntity<String> divSearchRes = restTemplate.exchange(URI.create(DIVSEARCHMOCK), HttpMethod.POST,requestEntity2,String.class);
        log.info(String.valueOf(responseEntity.getBody()));
        String dsr = divSearchRes.getBody();
        JSONArray jsonArray = JSONArray.parseArray(dsr);

        List<List<String>> dsrList = new ArrayList<>();
        String rvDesc = "";
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONArray item = jsonArray.getJSONArray(i);

            List<String> tempList = new ArrayList<>();
            tempList.add(item.getString(0));
            tempList.add(item.getString(1));
            String rv = "河流名称：" + tempList.get(0) + ", 河流代码：" + tempList.get(1) + "\n";
            dsrList.add(tempList);
            rvDesc += rv;
        }

        return rvDesc;
    }

    public String detailSearch(String query,String addm){
//        String addm = "";        //附加信息
        String detailSearchPrompt = "你是一位河流专家，你擅长使用“河流详情查询工具”来对河流进行检索，以辅助解决客户的问题。“河流详情查询工具”的输入格式为JSON格式，具体格式如下：\n" +
                "{\"工具名称\":\"河流详情查询工具\",\"河流代码\":[]}\n" +
                "json中的河流代码需要你根据用户问题和提供的相关信息来填入，河流代码可能为一个或多个，以列表的形式填入。\n" +
                "你现在需要借助“河流详情查询工具”来辅助解决用户的问题\n" +
                "你的回答只能包含JSON";
        List<MessagesDto> messages = new ArrayList<>();
        MessagesDto sysPrompt = new MessagesDto("system",detailSearchPrompt);
        String b1 = "无";
        MessagesDto shot1User = new MessagesDto("user","用户问题：查找河流代码为C0001H的河流的详细信息 附加信息："+b1+"\\n你的回答：");
        MessagesDto shot1Ass = new MessagesDto("assistant","{\"工具名称\":\"河流详情查询工具\",\"河流代码\":[\"C0001H\"]\n");
        String b2 = "“按行政区划查询河流名录工具”结果列表中河流的详细信息为：[{\"河流名称\":\"黄河\",\"河流代码\":\"D001\"},{\"河流名称\":\"秦淮河\",\"河流代码\":\"AA03\"},{\"河流名称\":\"澜沧江\",\"河流代码\":\"F001\"}]";
        MessagesDto shot2User = new MessagesDto("user","用户问题：查询所有“按行政区划查询河流名录工具”结果列表中河流的详细信息 附加信息："+b2+"\\n你的回答：");
        MessagesDto shot2Ass = new MessagesDto("assistant","{\"工具名称\":\"河流详情查询工具\",\"河流代码\":[\"D001\",\"AA03\",\"F001\"]\n");
        MessagesDto shotQuery = new MessagesDto("user","用户问题："+ query +"附加信息：" +addm+"\\n你的回答：");
        messages.add(sysPrompt);
        messages.add(shot1User);
        messages.add(shot1Ass);
        messages.add(shot2User);
        messages.add(shot2Ass);
        messages.add(shotQuery);

        LLMDto llmDto = new LLMDto();
        llmDto.setMessages(messages);

        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);

        String requestJson = JSON.toJSONString(llmDto);
        log.info("requestJson:{}",requestJson);
        HttpEntity<String> requestEntity = new HttpEntity<>(requestJson, httpHeaders);
        ResponseEntity<JSONObject> responseEntity = restTemplate.exchange(URI.create(BBEB_ASSISTANT_API), HttpMethod.POST,requestEntity,JSONObject.class);
        log.info(String.valueOf(responseEntity.getBody()));

        JSONObject ans = responseEntity.getBody();
        // 获取 choices 数组
        JSONArray choicesArray = ans.getJSONArray("choices");

        // 获取 content 元素的字符串表示
        String contentString = choicesArray.getJSONObject(0)
                .getJSONObject("message")
                .getString("content");
        log.info("去查第三方工具_详情");
        String name = "{\"name\":\"BBB\"}";
        HttpEntity<String> requestEntity2 = new HttpEntity<>(name, httpHeaders);
        ResponseEntity<String> getDetailRes = restTemplate.exchange(URI.create(GETDETAILMOCK), HttpMethod.POST,requestEntity2,String.class);
        log.info(String.valueOf(responseEntity.getBody()));
        String detail = getDetailRes.getBody();
        return detail;
    }
}
